package commons.base.nio;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

public class IOWorker implements Runnable, AutoCloseable {

	private Selector selector;
	private AtomicBoolean running = new AtomicBoolean(true);
	
	public IOWorker(SelectorProvider selectorProvider) throws IOException{
		selector = selectorProvider.openSelector();
	}
	
	public void regist(SocketChannel channel) throws ClosedChannelException{
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	@Override
	public void run() {
		try {
			while (running.get()) {
				selector.select();
				Set<SelectionKey> readyKeys = selector.selectedKeys();
				Iterator<SelectionKey> i = readyKeys.iterator();
				
				while (i.hasNext()) {
					SelectionKey sk = (SelectionKey) i.next();
					i.remove();
					if (sk.isValid() && sk.isReadable()) {
						doRead(sk);
					} else if (sk.isValid() && sk.isWritable()) {
						doWrite(sk);
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void doWrite(SelectionKey sk) {
		SocketChannel channel = (SocketChannel) sk.channel();
		
		// TODO process
		
		sk.interestOps(SelectionKey.OP_READ);
	}

	private void doRead(SelectionKey sk) {
		SocketChannel channel = (SocketChannel) sk.channel();
		
		// TODO logic
		
		sk.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
		selector.wakeup();
	}


	@Override
	public void close() throws Exception {
		running.set(false);
		
		selector.close();
	}

}
